/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.web.gwt.form.client.widget.item.impl;

import java.util.ArrayList;
import java.util.List;

import com.genia.toolbox.web.gwt.basics.client.GwtHelper;
import com.genia.toolbox.web.gwt.basics.client.widget.FileUploadWidget;
import com.genia.toolbox.web.gwt.form.client.CssNames;
import com.genia.toolbox.web.gwt.form.client.form.MultipleFileUploadItem;
import com.genia.toolbox.web.gwt.form.client.process.ProcessSortable;
import com.genia.toolbox.web.gwt.form.client.widget.SortableWidget;
import com.genia.toolbox.web.gwt.form.client.widget.item.ItemWidgetModifyListener;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * widget that represents a file upload control.
 */
public class MultipleFileUploadItemWidget
    extends AbstractSimpleItemWidget<MultipleFileUploadItem>
    implements SortableWidget
{

  /**
   * the {@link ChangeListener} called each time a sub file is modified.
   */
  private class FileUploadChangeListener
      implements ChangeListener
  {

    /**
     * fired when a widget changes, where 'change' is defined by the widget
     * sending the event.
     * 
     * @param sender
     *          the widget that has changed
     * @see com.google.gwt.user.client.ui.ChangeListener#onChange(com.google.gwt.user.client.ui.Widget)
     */
    public void onChange(Widget sender)
    {
      FileUploadWidget fileUploadWidget = (FileUploadWidget) sender;
      if (fileUploadWidget.getValue() == null) {
        // an already defined file just get removed
        fileUploadWidgets.remove(fileUploadWidget);
        valuesPanel.remove(fileUploadWidget);
      }
      else {
        // the empty upload file control just
        // got a new value.
        fileUploadWidgets.add(fileUploadWidget);
        valuesPanel.add(fileUploadWidget);
        addNewFileUploadWidget();
      }
      modifyListeners.onModify(MultipleFileUploadItemWidget.this);
    }

  }

  /**
   * the {@link ChangeListener} called each time a sub file is modified.
   */
  private final transient FileUploadChangeListener fileUploadChangeListener = new FileUploadChangeListener();

  /**
   * list containing the values.
   */
  private List<FileUploadWidget> fileUploadWidgets = new ArrayList<FileUploadWidget>();

  /**
   * the registered {@link ItemWidgetModifyListener}.
   */
  private final transient ItemWidgetModifyListenerCollection modifyListeners = new ItemWidgetModifyListenerCollection();

  /**
   * the panel presenting the files.
   */
  private final transient HorizontalPanel panel = new HorizontalPanel();

  /**
   * the panel containing the files to upload.
   */
  private final transient VerticalPanel valuesPanel;

  /**
   * the panel containing the empty upload file widget.
   */
  private final transient Panel newFilePanel = new FlowPanel();

  /**
   * the list of all the {@link Widget} that must be modify to update the error
   * message.
   */

  private final transient Widget[] widgetsToToggle = new Widget[] { panel };



  /**
   * constructor.
   * 
   * @param item
   *          the item describing this element.
   */
  public MultipleFileUploadItemWidget(MultipleFileUploadItem item)
  {
    super(item);

    final Label uploadLabelWidget = new Label();
    GwtHelper.fillText(uploadLabelWidget, item.getLabelKey());

    final Panel vPanel = new VerticalPanel();

    panel.add(uploadLabelWidget);
    panel.add(vPanel);

    // set the styleName.
    panel.addStyleName(CssNames.MULTIPLE_FILE_UPLOAD_PANEL_CSS_STYLE);
    panel.addStyleName(item.getName());

    valuesPanel = ProcessSortable.getVerticalPanel(this);
    vPanel.add(valuesPanel);
    vPanel.add(newFilePanel);

    addNewFileUploadWidget();
    initWidget(panel);
  }



  /**
   * add a listener that is called each time the value of this object change.
   * 
   * @param modifyListener
   *          the callback
   * @see com.genia.toolbox.web.gwt.form.client.widget.item.SimpleItemWidget#addModifyListener(com.genia.toolbox.web.gwt.form.client.widget.item.ItemWidgetModifyListener)
   */
  public void addModifyListener(ItemWidgetModifyListener modifyListener)
  {
    modifyListeners.add(modifyListener);
  }



  /**
   * Add a new empty {@link FileUploadWidget}.
   */
  private void addNewFileUploadWidget()
  {
    FileUploadWidget fileUploadWidget = new FileUploadWidget();
    fileUploadWidget.addChangeListener(fileUploadChangeListener);
    newFilePanel.add(fileUploadWidget);
  }



  /**
   * returns the current values of this item.
   * 
   * @return a {@link List} of {@link String} representing the current values of
   *         this item
   * @see com.genia.toolbox.web.gwt.form.client.widget.item.SimpleItemWidget#getValues()
   */
  public List<String> getValues()
  {
    List<String> res = new ArrayList<String>();
    for (FileUploadWidget fileUploadWidget : fileUploadWidgets) {
      res.add(fileUploadWidget.getValue());
    }
    return res;
  }



  /**
   * returns an array containing all the widget that the setErrorMessage must
   * modify.
   * 
   * @return an array containing all the widget that the setErrorMessage must
   *         modify
   * @see com.genia.toolbox.web.gwt.form.client.widget.item.impl.AbstractSimpleItemWidget#getWidgetsToToggle()
   */
  @Override
  protected Widget[] getWidgetsToToggle()
  {
    return widgetsToToggle;
  }



  /**
   * move the given value to the given position.
   * 
   * @param oldIndex
   *          the index of the value to move
   * @param newIndex
   *          the index of the final destination of the value
   * @see com.genia.toolbox.web.gwt.form.client.widget.SortableWidget#moveValue(int,
   *      int)
   */
  public void moveValue(int oldIndex, int newIndex)
  {
    ProcessSortable.move(fileUploadWidgets, oldIndex, newIndex);
    modifyListeners.onModify(this);
  }



  /**
   * set the current values of this item.
   * 
   * @param values
   *          a {@link List} of {@link String} representing the new values of
   *          this item
   * @see com.genia.toolbox.web.gwt.form.client.widget.item.SimpleItemWidget#setValues(java.util.List)
   */
  public void setValues(List<String> values)
  {
    valuesPanel.clear();
    fileUploadWidgets.clear();
    if (values != null) {
      for (final String value : values) {
        FileUploadWidget fileUploadWidget = new FileUploadWidget();
        fileUploadWidget.setValue(value);
        fileUploadWidget.addChangeListener(fileUploadChangeListener);
        fileUploadWidgets.add(fileUploadWidget);
        valuesPanel.add(fileUploadWidget);
      }
    }
    addNewFileUploadWidget();
    modifyListeners.onModify(this);
  }
}
